﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using eeenno.ReaderEngine.Utilities;

namespace eeenno.ReaderEngine.Adapters
{
    /// <summary>
    /// Provides functionality for parsing Xml data returned from Google Reader
    /// </summary>
    public class XmlEngine
    {
        public static string _NO_TAG_KEYWORD = "Untagged";
        private static string _NAME_KEYWORD = "name";

        private static string _SUB_KEYWORD = "subscriptions";
        private static int _SUB_URL_ID = 0;
        private static int _SUB_TITLE_ID = 1;
        private static int _SUB_CATEGORY_ID = 2;

        private static string _UNREAD_KEYWORD = "unreadcounts";
        private static int _UNREAD_TAG_ID = 0;
        private static int _UNREAD_COUNT_ID = 1;

        private static string _TAG_KEYWORD = "tags";
        private static int _TAG_ID = 0;

        /// <summary>
        /// Returns the xml sub tree with the master element with the attribute name of "node"
        /// </summary>
        /// <param name="data"></param>
        /// <param name="node"></param>
        /// <returns></returns>
        public static XmlDocument GetXmlDocument(string data, string node)
        {
            XmlDocument ret_val = new XmlDocument();
            using(XmlTextReader reader = new XmlTextReader(new StringReader(data)))
            {
                try
                {
                    while (reader.Read())
                    {
                        if (reader.NodeType == XmlNodeType.Element && reader[_NAME_KEYWORD] != null && reader[_NAME_KEYWORD].Equals(node))
                        {
                            break;
                        }
                    }
                    ret_val.Load(reader);
                }
                catch (XmlException e)
                {

                }
            }

            return ret_val;
        }

        /// <summary>
        /// Returns the xml sub tree with the master element with the attribute name of "node"
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static XmlDocument GetXmlDocument(string data)
        {
            XmlDocument ret_val = new XmlDocument();
            using (XmlTextReader reader = new XmlTextReader(new StringReader(data)))
            {
                try
                {
                    ret_val.Load(reader);
                }
                catch (XmlException e)
                {
                }
            }

            return ret_val;
        }

        public static string ProcessShortenenedUrl(string data)
        {
            int start = data.IndexOf("<userHash>");
            int end = data.IndexOf("</userHash>");
            start += 10;
            return "http://bit.ly/" + data.Substring(start, end - start);         
        }

        /// <summary>
        /// Parses needed information regarding tag list
        /// </summary>
        /// <param name="tag_list_data">xml containing tag list information</param>
        /// <returns>tag data</returns>
        public static string[] ProcessTagList(string tag_list_data)
        {
            string[] ret_val;

            XmlDocument xml_doc = GetXmlDocument(tag_list_data, _TAG_KEYWORD);
            ret_val = new string[xml_doc.ChildNodes[0].ChildNodes.Count + 1];
            
            for (int i = 0; i < ret_val.Length - 1; i++)
            {
                string[] temp = xml_doc.ChildNodes[0].ChildNodes[i].ChildNodes[_TAG_ID].InnerText.Split('/');
                ret_val[i] = temp[temp.Length - 1];
            }
            ret_val[ret_val.Length - 1] = _NO_TAG_KEYWORD;

            return ret_val;
        }

        /// <summary>
        /// Parses needed information regarding unread counts
        /// 0 - label
        /// 1 - unread count
        /// </summary>
        /// <param name="unread_count_data">xml containing unread count data</param>
        /// <returns>unread counts data</returns>
        public static string[] ProcessUnreadCounts(string unread_count_data)
        {
            string[] ret_val;

            XmlDocument xml_doc = GetXmlDocument(unread_count_data, _UNREAD_KEYWORD);
            ret_val = new string[xml_doc.ChildNodes[0].ChildNodes.Count];
            for (int i = 0; i < ret_val.Length; i++)
            {
                ret_val[i] = String.Empty;
                string[] temp = xml_doc.ChildNodes[0].ChildNodes[i].ChildNodes[_UNREAD_TAG_ID].InnerText.Split('/');
                //determines what is a tag and a subscription
                if (temp[0].Equals("user"))
                {
                    ret_val[i] += temp[temp.Length - 1];
                }
                else
                {
                    ret_val[i] += xml_doc.ChildNodes[0].ChildNodes[i].ChildNodes[_UNREAD_TAG_ID].InnerText;
                }
                ret_val[i] += "~" + xml_doc.ChildNodes[0].ChildNodes[i].ChildNodes[_UNREAD_COUNT_ID].InnerText;
            }

            return ret_val;
        }

        /// <summary>
        /// Process subscription list atom data and extracts subscription information
        /// [0] subscription url
        /// [1] subscription title
        /// [2] subscription tag
        /// </summary>
        /// <param name="data">Atom feed state containing subscription information</param>
        /// <returns>subscription data</returns>
        public static string[] ProcessSubscriptionList(string subscription_data)
        {
            string[] ret_val;       

            XmlDocument xml = GetXmlDocument(subscription_data, _SUB_KEYWORD);            
            ret_val = new string[xml.ChildNodes[0].ChildNodes.Count];
            //iterate through each node
            for (int i = 0; i < ret_val.Length; i++)
            {
                ret_val[i] += xml.ChildNodes[0].ChildNodes[i].ChildNodes[_SUB_URL_ID].InnerText + "~";
                ret_val[i] += xml.ChildNodes[0].ChildNodes[i].ChildNodes[_SUB_TITLE_ID].InnerText;

                XmlNode current_node = xml.ChildNodes[0].ChildNodes[i].ChildNodes[_SUB_CATEGORY_ID].ChildNodes[0];
                string tag = _NO_TAG_KEYWORD;
                if (current_node != null)
                {
                    tag = current_node.ChildNodes[1].InnerText;
                }
                ret_val[i] += "~" + tag;
            }

            return ret_val;
        }
    }
}
